require(["drag", "ui"], (drag, ui) => {

    // 选择模式弹出框
    class Select {
        constructor() {
            let body = ui.$("body[0]");

            // 主窗口
            this.window = ui.addNode(body, "div", "innerEnd", {
                class: "lyx-window",
                style: {
                    display: "none"
                }
            });

            // 标题栏
            this.title = ui.addNode(this.window, "div", "innerEnd", {
                class: "lyx-title"
            });

            ui.addNode(this.title, "h5", "innerEnd", {
                style: {
                    margin: 0,
                    float: "left"
                }
            }).innerHTML = "元素选择器";

            // 关闭按钮
            this.close = ui.addNode(this.title, "span", "innerEnd")
            this.close.innerHTML = "×";

            ui.hander.add(this.close, "click", () => {
                if (this.onClose) {
                    this.onClose();
                }
                this.hide();
            });

            // 主窗口内容
            this.content = ui.addNode(this.window, "div", "innerEnd", {
                style: {
                    height: 85
                }
            });

            ui.addNode(this.content, "div", "innerEnd", {
                style: {
                    paddingLeft: 10,
                    height: 40,
                    lineHeight: 40
                }
            }).innerHTML = "拖动圆点指针选择元素层级";

            this.view = ui.addNode(this.content, "div", "innerEnd", {
                class: "lyx-view"
            });

            this.pointer = ui.addNode(this.content, "div", "innerEnd", {
                class: "lyx-pointer"
            });

            ui.addNode(this.pointer, "div", "innerEnd");

            let button = ui.addNode(this.window, "div", "innerEnd", {
                class: "lyx-button"
            });

            // 选择其它元素按钮
            this.select = ui.addNode(button, "div", "innerEnd", {
                class: "lyx-select"
            });
            this.select.innerHTML = "选择其它元素";
            ui.hander.add(this.select, "click", () => {
                if (this.onSelect) {
                    this.onSelect();
                }
            });

            // 取消选择模式按钮
            this.cancelSelect = ui.addNode(button, "div", "innerEnd", {
                class: "lyx-select",
                style: {
                    display: "none"
                }
            });
            this.cancelSelect.innerHTML = "取消选择模式";
            ui.hander.add(this.cancelSelect, "click", () => {
                this.hide();
                if (this.onClose) {
                    this.onClose();
                }
            });

            // 拦截按钮
            this.intercept = ui.addNode(button, "div", "innerEnd", {
                class: "lyx-intercept"
            });
            this.intercept.innerHTML = "拦截";
            ui.hander.add(this.intercept, "click", () => {
                if (this.onIntercept) {
                    this.onIntercept();
                }
            });

            // 预览按钮
            this.preview = ui.addNode(button, "div", "innerEnd", {
                class: "lyx-preview"
            });
            this.preview.innerHTML = "预览";
            ui.hander.add(this.preview, "click", () => {
                let status = this.preview.innerHTML == "预览";
                this.previewMode(status);
                if (this.onPreview) {
                    this.onPreview(status);
                }
            });

            // 添加窗口拖动
            drag(this.title, undefined, {
                mappingEl: this.window,
                closeTarget: true
            });

            // 添加层级指针拖动
            drag(this.pointer, {
                move: drag => {
                    if (this.onDragPointer) {
                        this.onDragPointer(drag);
                    }
                }
            });
        }

        // 隐藏窗口
        hide() {
            this.window.style.display = "none";
        }

        // 显示窗口
        show() {
            this.window.style.display = "";
        }

        // 选择模式
        selectMode(status) {
            this.content.style.display = status ? "" : "none";
            this.select.style.display = status ? "" : "none";
            this.cancelSelect.style.display = status ? "none" : "";
            this.intercept.style.display = status ? "" : "none";
            this.preview.style.display = status ? "" : "none";
            this.preview.innerHTML = status ? "预览" : "取消预览";
        }

        // 预览模式
        previewMode(status) {
            this.preview.innerHTML = status ? "取消预览" : "预览";
            this.content.style.display = status ? "none" : "";
            this.select.style.display = status ? "none" : "";
        }

    }

    // 层级条
    class Bar {
        // parent是将层级条插入的目标元素
        constructor(parent) {
            this.list = [];
            this.path = 0;
            this.width = 0;
            this.parent = parent;
        }

        setPath(path) {
            this.path = path;
            this.width = (400 / path.length) - 1;
            let i = 0;
            let len = 0;
            for (len = this.list.length; i < len && i < path.length; i++) {
                ui.css(this.list[i], {
                    width: this.width,
                    display: ""
                });
                this.list[i].innerHTML = path[i];
            }

            if (i < path.length) {
                for (; i < path.length; i++) {
                    this.list.push(ui.addNode(this.parent, "div", "innerEnd", {
                        style: {
                            width: this.width
                        }
                    }));
                    this.list[i].innerHTML = path[i];
                }
            }
            else {
                for (; i < len; i++) {
                    ui.css(this.list[i], {
                        width: 0,
                        display: "none"
                    });
                }
            }
        }
    }

    class Border {
        constructor() {
            this.container = ui.addNode(ui.$("body[0]"), "div", "innerEnd", {
                style: {
                    height: 0,
                    width: 0
                }
            });

            let baseStyle = {
                position: "fixed",
                top: 0,
                left: 0,
                background: "#8BC34A",
                zIndex: 99999
            };

            this.list = new Lyx.queue();

            this.top = ui.addNode(this.container, "div", "innerEnd", {
                style: Lyx.extend({}, [baseStyle, {
                    width: 0,
                    height: 5
                }])
            });

            this.left = ui.addNode(this.container, "div", "innerEnd", {
                style: Lyx.extend({}, [baseStyle, {
                    width: 5,
                    height: 0
                }])
            });
            this.right = ui.addNode(this.container, "div", "innerEnd", {
                style: Lyx.extend({}, [baseStyle, {
                    width: 5,
                    height: 0
                }])
            });
            this.bottom = ui.addNode(this.container, "div", "innerEnd", {
                style: Lyx.extend({}, [baseStyle, {
                    width: 0,
                    height: 12,
                    fontSize: 10,
                    lineHeight: 12,
                    textAlign: "right",
                    color: "#fff"
                }])
            });
        }

        /**
         * 定位目标，在其周围生成边框
         * @param {*} el 
         */
        position(el) {
            this.target = el;
            let position = el.getBoundingClientRect();
            ui.css(this.top, {
                left: position.left,
                top: position.top - 5,
                width: position.width
            });
            ui.css(this.left, {
                left: position.left - 5,
                top: position.top - 5,
                height: position.height + 17
            });
            ui.css(this.right, {
                left: position.left + position.width,
                top: position.top - 5,
                height: position.height + 17
            });
            ui.css(this.bottom, {
                left: position.left,
                top: position.top + position.height,
                width: position.width
            });
        };

        // 设置路径
        setInnerHTML(el, exclude) {
            let str = "";
            while (el.nodeName != "BODY") {
                if (exclude == el) {
                    return false;
                }
                str = el.nodeName.toLowerCase() + " " + str;
                el = el.parentNode;
            }
            this.bottom.innerHTML = str;
            return true;
        }

        // 显示边框
        show() {
            ui.css(this.top, {
                display: ""
            });
            ui.css(this.left, {
                display: ""
            });
            ui.css(this.right, {
                display: ""
            });
            ui.css(this.bottom, {
                display: ""
            });
        }

        // 隐藏边框
        hide() {
            ui.css(this.top, {
                display: "none"
            });
            ui.css(this.left, {
                display: "none"
            });
            ui.css(this.right, {
                display: "none"
            });
            ui.css(this.bottom, {
                display: "none"
            });
        }
    }

    let select = new Select();
    let border = new Border();
    let bar = new Bar(select.view);

    select.onClose = () => {
        select.hide();
        border.hide();
    }

    select.onDragPointer = (drag) => {
        // 锁定纵轴
        drag.style.top = drag.top;
        
        // 获取当前位置对应的索引
        let index = Math.round((drag.style.left - 41) / bar.width);
        if (index == 0) {
            index = 1;
        }

        // 更新指针位置
        drag.style.left = index * bar.width + 41;

        // 锁定范围
        drag.style.left = Lyx.scope(35, 441, drag.style.left);

        // 定位元素
        border.position(border.list[index - 1]);

        border.bottom.innerHTML = getPath(border.list, index - 1);

        for (let i = 0; i < bar.list.length; i ++) {
            ui.css(bar.list[i], {
                background: i < index ? "#9ad752" : "#ffa400"
            });
        }

    }

    select.onPreview = (status) => {
        border.target.style.display = status ? "none" : "";
        border[status ? "hide" : "show"]();
    }

    select.onSelect = () => {
        select.show();
        select.selectMode(false);
        ui.hander.add("body[0]", "click", sure);
        ui.hander.add("body[0]", "mouseover", selectView);
    }

    select.onIntercept = () => {
        let list = border.list.slice(0, -3).reverse();
        let pathList = [];
        for (let i = 1; i < list.length; i ++) {
            let parent = list[i - 1];
            let id = list[i].getAttribute("id");
            if (id == null) {
                parent.childNodes.forEach((node, index) => {
                    if (node == list[i]) {
                        pathList.push({
                            parentNodeName: parent.nodeName,
                            nodeName: node.nodeName,
                            index: index
                        });
                        return false;
                    }
                });
            }
            else {
                pathList.push({
                    parentNodeName: parent.nodeName,
                    nodeName: list[i].nodeName,
                    id: id
                });
            }
        }
        let localData = localStorage.getItem("lyx-filter");
        if (localData != null) {
            localData = JSON.parse(localData);
        }
        else {
            localData = [];
        }
        localData.push(pathList);
        localStorage.setItem("lyx-filter", JSON.stringify(localData));
        border.target.style.display = "none";
        select.onClose();
    }

    // 获取元素路径
    function getPath(list, begin) {
        let path = [];
        let i = begin || 0;
        while (i < list.length) {
            // 排除选择框和边框
            if (list[i] == select.window || list[i] == border.container) {
                return false;
            }
            let nodeName = list[i].nodeName.toLowerCase();
            if (nodeName == "body") break; 
            path.push(nodeName);;
            i ++;
        }
        return path;
    }

    // 选择视图
    function selectView(event) {
        let path = getPath(event.path);
        if (path != false) {
            border.list = event.path;
            border.bottom.innerHTML = path.join(" ");
            border.position(event.target);
        }
    }

    // 确定选择
    function sure(event) {
        let path = getPath(event.path);
        if (path != false) {
            bar.setPath(path);
            ui.css(select.pointer, {
                left: bar.width + 41
            });
            ui.css(bar.list[0], {
                background: "#9ad752"
            });
            select.selectMode(true);
            ui.hander.remove("body[0]", "click", sure);
            ui.hander.remove("body[0]", "mouseover", selectView);
        }
    }

    select.onSelect();

    let local = localStorage.getItem("lyx-filter");
    if (local != null) {
        local = JSON.parse(local);
        for (let i = 0; i < local.length; i ++) {
            let parent = ui.$("body[0]");
            pathList = local[i];
            pathList.forEach(condition => {
                if (condition.id) {
                    parent = ui.$("#" + condition.id, parent);
                }
                else {
                    parent = parent.childNodes[condition.index];
                }
            });
            if (parent) {
                parent.style.display = "none";
            }
        }
    }
});